/**
 * @file nivel2.h
 * @brief Fichero de cabecera de funciones de Nivel 2.
 *
 * Fichero que contiene los prototipos de las funciones de Nivel 2 del estandar HDLC.
 */

#include <netinet/in.h>
#include "nivel1a.h"
#include "datagramBuffer.h"

#ifndef LEVEL2_H
#define LEVEL2_H

#define BANDWIDTH 1											/*!< Ancho de ventana*/

#define N2_T_INTERRUPCION 0									/*!< Tiempo de espera transmitido al Nivel 1a*/
#define N2_TMAX_CONFIRM 100									/*!< Tiempo de espera a llegada de mensajes*/
#define N2_MAX_REINT 3										/*!< Numero de reintentos*/

#define N2_MAX_DATA_SIZE 255								/*!< Tamanno maximo de los mensajes de Nivel 2*/
#define HDLC_HEADER_SIZE 2									/*!< Tamanno de las cabeceras de Nivel 2*/

typedef int (*tpfNotificacionDesdeNivel2) (int, const BYTE *);			/*!< Funcion de notificacion de Nivel 2*/

/**
* @brief Inicializa el Nivel 2.
*
* Inicializa la infraestructura necesaria para obtener acceso a las
* funcionalidades del Nivel 2.
*
* Nota: Esta funcion no tiene efecto si el Nivel 2 se ha inicializado previamente.
*
* @param notifyFunction Funcion de notificacion desde Nivel 2.
* @return ETH_OK si correcto, ETH_ERROR si error.
*/
int IniciarNivel2(tpfNotificacionDesdeNivel2 notifyFunction);

/**
* @brief Finaliza el Nivel 2.
*
* Libera los recursos reservado al inicializarse el Nivel 2.
*
* Nota: Esta funcion no tiene efecto si el Nivel 2 no ha sido iniciado.
*
* @return ETH_OK si correcto, ETH_ERROR si error.
*/
int FinalizarNivel2();

/**
* @brief Solicita una conexion remota con DireccionEthernetDestino.
*
* Comunica a la estacion con MAC DireccionEthernetDestino que desea establecer
* comunicacion con ella. Si no recibe respuesta, retorna ETH_ERROR.
*
* @param DireccionEthernetDestino Direccion MAC de la estacion con la que se quiere
* establecer conexion.
* @return ETH_OK si correcto, ETH_ERROR si error.
*/
int SolicitarConexion(BYTE *DireccionEthernetDestino);

/**
* @brief Acepta una conexion de DireccionEthernetDestino durante timeout milisegundos.
*
* Bloquea el proceso en ejecucion durante, a lo sumo timeout milisegundos, a la espera
* de una solicitud de conexion de DireccionEthernetDestino. Si la direccion MAC suministrada
* es la direccion de difusion (FF:FF:FF:FF:FF:FF), acepta la primera conexion entrante.
*
* @param DireccionEthernetDestino Direccion MAC de la estacion con la que se quiere
* establecer conexion.
* @return ETH_OK si correcto, ETH_ERROR si error.
*/
int AceptarConexion(BYTE *DireccionEthernetDestino, int timeout);

/**
* @brief Envia datos a la estacion remota.
*
* Envia size byte's, contenidos en data, a la estacion con la que se ha establecido
* conexion previa.
* Es un servicio de entrega fiable que garantiza la llegada de los datos o, de no
* ser posible, retorna un error.
*
* @param data Array de byte's a enviar.
* @param size Tamanno del paquete a enviar.
* @return ETH_OK si correcto, ETH_ERROR si error.
*/
int EnviarDatos(BYTE *data, int size);

/**
* @brief Recibe datos de la estacion remota.
*
* Recibe datos provenientes de la estacion con la que, previamente, se ha establecido
* conexion, volcandolos sobre data. Bloquea el proceso durante, a lo sumo, timeout milisegundos
* a la espera de paquetes entrantes. Si timeout = 0, el bloqueo es indefinido hasta la llegada
* de mensajes.
*
* Nota: Se supone que la zona de memoria apuntada por data es lo suficientemente grande
* como para albergar el paquete entrante.
*
* @param data Zona de memoria sobre la que se volcara el mensaje.
* @param size Tamanno del paquete a enviar.
* @return ETH_TIMEOUT si el tiempo de espera a expirado, ETH_ERROR si error. Si correcto, retorna
* el tamanno del mensaje recibido.
*/
int RecibirDatos(BYTE *data, int timeout);

/**
* @brief Desconecta el host de la conexion.
*
* Solicita desconexion a la estacion remota, suspendiendose a la espera de respuesta.
* Si no se obtiene confirmacion, realiza una desconexion forzosa y retorna ETH_ERROR.
*
* @return ETH_OK si correcto, ETH_ERR si error.
*/
int Desconectar();

#endif
